﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AspectCore.Extensions.Reflection;
using Microsoft.Win32;
using netCoreStudy.Attr.QueryAttr;

namespace netCoreStudy.Express
{
	/// <summary>
	/// 公共 reflector 字典
	/// 这样缓存下来，你调用 GetProperties、GetProperty、GetReflector 的次数就会减少很多了。
	/// 当然 你还可以再优化一下，把这个方法设计成可以单独只取对应属性的 reflector
	/// 因为你的 类一般说来在运行过程中 结构不会发生变化。所以这个缓存可以整个程序全局使用。
	/// 你可以尝试一下 在类里再封装一个 方法，获取reflector。先判断
	/// 缓存中有没有对应的 reflector，有就直接用。没有就 获取并放入缓存。
	/// 没缓存的话，你会反复获取 property 和 reflector。获取后，你又只调用了一次的话，所以看不出来 差距。
	/// 其实取 reflector 也有消耗的。缓存起来，每个属性只取一次reflector 。剩下的操作就全是 GetValue ，性能就起来了。
	/// 所以先让能 考虑把 reflector 缓存下来呢。
	/// 他这里的性能提升是体现在 propertyinfo.GetValue 和 reflector.GetValue 的对比上。
	/// 先取 properties 再循环 每个  property 取 reflector,通过 reflector取值 。
	/// </summary>
	public static class ReflectorDic
	{
		//字典 dic<type,IEnumerable<PropertyReflector>> 类型 
		private static readonly Dictionary<Type, PropertyReflector[]>
			PropReflectors =
				new Dictionary<Type, PropertyReflector[]>();

		private static readonly Dictionary<Type, TypeReflector> TypeInfoReflector =
			new Dictionary<Type, TypeReflector>();

		/// <summary>
		/// 获取 类型 type 下的所有 属性 的 reflector
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static PropertyReflector[] GetPropReflector(Type type)
		{
			PropertyReflector[] result;
			lock (PropReflectors)
			{
				if (!PropReflectors.ContainsKey(type))
				{
					result = type.GetProperties().Select(d => d.GetReflector()).ToArray();
					PropReflectors.Add(type, result);
				}
				else
				{
					result = PropReflectors[type];
				}
			}

			return result;
		}

		/// <summary>
		/// 获取 类型 type 下的所有 属性 的 reflector 扩展方法 写法
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static PropertyReflector[] GetProps(this Type type)
		{
			PropertyReflector[] result;
			lock (PropReflectors)
			{
				if (!PropReflectors.ContainsKey(type))
				{
					result = type.GetProperties().Select(d => d.GetReflector()).ToArray();
					PropReflectors.Add(type, result);
				}
				else
				{
					result = PropReflectors[type];
				}
			}

			return result;
		}

		/// <summary>
		/// 获取 当前 type 的 信息 
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static TypeReflector GetTypeInfo(Type type)
		{
			TypeReflector res;
			lock (TypeInfoReflector)
			{
				if (!TypeInfoReflector.ContainsKey(type))
				{
					TypeInfo typeInfo = type.GetTypeInfo();
					res = typeInfo.GetReflector();
					TypeInfoReflector.Add(type, res);
				}
				else
				{
					res = TypeInfoReflector[type];
				}
			}

			return res;
		}
	}
}